home *** CD-ROM | disk | FTP | other *** search
- Subject: v09i030: A TECO text editor, Part03/04
- Newsgroups: mod.sources
- Approved: rs@mirror.TMC.COM
-
- Submitted by: genrad!mlf
- Mod.sources: Volume 9, Issue 30
- Archive-name: teco/Part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If this archive is complete, you will see the message:
- # "End of archive 3 (of 4)."
- # Contents: te_exec1.c te_exec2.c
- # Wrapped by rs@mirror on Thu Mar 12 19:54:32 1987
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo shar: Extracting \"te_exec1.c\" \(21012 characters\)
- if test -f te_exec1.c ; then
- echo shar: Will not over-write existing file \"te_exec1.c\"
- else
- sed "s/^X//" >te_exec1.c <<'END_OF_te_exec1.c'
- X/* TECO for Ultrix Copyright 1986 Matt Fichtenbaum */
- X/* This program and its components belong to GenRad Inc, Concord MA 01742 */
- X/* They may be copied if this copyright notice is included */
- X
- X/* te_exec1.c continue executing commands 1/8/87 */
- X#include "te_defs.h"
- X
- Xexec_cmds1()
- X {
- X char command; /* command character */
- X int cond; /* conditional in progress */
- X
- X switch (command = mapch_l[cmdc])
- X {
- X/* operators */
- X
- X case '+':
- X esp->exp = (esp->flag1) ? esp->val1 : 0;
- X esp->flag1 = 0;
- X esp->op = OP_ADD;
- X break;
- X
- X case '-':
- X esp->exp = (esp->flag1) ? esp->val1 : 0;
- X esp->flag1 = 0;
- X esp->op = OP_SUB;
- X break;
- X
- X case '*':
- X esp->exp = (esp->flag1) ? esp->val1 : 0;
- X esp->flag1 = 0;
- X esp->op = OP_MULT;
- X break;
- X
- X case '/':
- X esp->exp = (esp->flag1) ? esp->val1 : 0;
- X esp->flag1 = 0;
- X esp->op = OP_DIV;
- X break;
- X
- X case '&':
- X esp->exp = (esp->flag1) ? esp->val1 : 0;
- X esp->flag1 = 0;
- X esp->op = OP_AND;
- X break;
- X
- X case '#':
- X esp->exp = (esp->flag1) ? esp->val1 : 0;
- X esp->flag1 = 0;
- X esp->op = OP_OR;
- X break;
- X
- X case ')':
- X if ((!esp->flag1) || (esp <= &estack[0])) ERROR(E_NAP);
- X --esp;
- X esp->val1 = (esp+1)->val1; /* carry value from inside () */
- X esp->flag1 = 1;
- X break;
- X case ',':
- X if (!esp->flag1) ERROR(E_NAC);
- X else esp->val2 = esp->val1;
- X esp->flag2 = 1;
- X esp->flag1 = 0;
- X break;
- X
- X case CTL (_):
- X if (!esp->flag1) ERROR(E_NAB);
- X else esp->val1 = ~esp->val1;
- X break;
- X
- X/* radix control */
- X
- X case CTL (D):
- X ctrl_r = 10;
- X esp->flag1 = 0;
- X esp->op = OP_START;
- X break;
- X
- X case CTL (O):
- X ctrl_r = 8;
- X esp->flag1 = 0;
- X esp->op = OP_START;
- X break;
- X
- X case CTL (R):
- X if (!esp->flag1) /* fetch it */
- X {
- X esp->val1 = ctrl_r;
- X esp->flag1 = 1;
- X }
- X else
- X {
- X if ((esp->val1 != 8) && (esp->val1 != 10) && (esp->val1 != 16)) ERROR(E_IRA);
- X ctrl_r = esp->val1;
- X esp->flag1 = 0;
- X esp->op = OP_START;
- X }
- X break;
- X
- X/* other commands */
- X
- X case CTL (C): /* 1 ^C stops macro execution, 2 exit */
- X if (peekcmdc(CTL (C))) exitflag = -1; /* 2 ^C: stop execution and exit */
- X else if (msp <= &mstack[0]) exitflag = 1; /* 1 ^C: in command string: stop execution */
- X else --msp; /* in a macro - pop it */
- X break;
- X
- X case CTL (X): /* search mode flag */
- X set_var(&ctrl_x);
- X break;
- X
- X case 'e':
- X do_e();
- X break;
- X
- X case 'f':
- X do_f();
- X break;
- X/* macro call, iteration, conditional */
- X
- X case 'm': /* macro call */
- X mm = getqspec(0, getcmdc(trace_sw)); /* read the macro name */
- X if (msp > &mstack[MSTACKSIZE-1]) ERROR(E_PDO); /* check room for another level */
- X ++msp; /* push stack */
- X cptr.p = qreg[mm].f; /* to stack entry, put q-reg text start */
- X cptr.flag = cptr.c = cptr.dot = 0; /* initial char position, iteration flag */
- X cptr.z = qreg[mm].z; /* number of chars in macro */
- X break;
- X
- X case '<': /* begin iteration */
- X if ((esp->flag1) && (esp->val1 <= 0)) /* if this is not to be executed */
- X find_enditer(); /* just skip the intervening stuff */
- X else
- X {
- X if (!cptr.il) /* does this macro have an iteration list? */
- X {
- X cptr.il = (struct is *) get_dcell(); /* no, make one for it */
- X cptr.il->b = NULL; /* with NULL reverse pointer */
- X }
- X else if (cptr.flag & F_ITER) /* is there an iteration in process? */
- X {
- X if (!cptr.il->f) /* yes, if it has no forward pointer */
- X {
- X cptr.il->f = (struct is *) get_dcell(); /* append a cell to the iteration list */
- X cptr.il->f->b = cptr.il; /* and link it in */
- X }
- X cptr.il = cptr.il->f; /* and advance the iteration list pointer to it */
- X }
- X cptr.flag |= F_ITER; /* set iteration flag */
- X cptr.il->p = cptr.p; /* save start of iteration */
- X cptr.il->c = cptr.c;
- X cptr.il->dot = cptr.dot;
- X if (cptr.il->dflag = esp->flag1) /* if there is an argument, set the "def iter" flag */
- X {
- X cptr.il->count = esp->val1; /* save the count */
- X esp->flag1 = 0; /* and consume the arg */
- X }
- X }
- X break;
- X
- X case '>': /* end iteration */
- X if (!(cptr.flag & F_ITER)) ERROR(E_BNI); /* error if > not in iteration */
- X pop_iteration(0); /* decrement count and pop conditionally */
- X esp->flag1 = esp->flag2 = 0; /* consume arguments */
- X esp->op = OP_START;
- X break;
- X
- X case ';': /* semicolon iteration exit */
- X if (!(cptr.flag &F_ITER)) ERROR(E_SNI); /* error if ; not in iteration */
- X if ( ( ((esp->flag1) ? esp->val1 : srch_result) >= 0) ? (!colonflag) : colonflag) /* if exit */
- X {
- X find_enditer(); /* get to end of iteration */
- X pop_iteration(1); /* and pop unconditionally */
- X }
- X esp->flag1 = colonflag = 0; /* consume arg and colon */
- X esp->op = OP_START;
- X break;
- X/* conditionals */
- X
- X case '"':
- X if (!esp->flag1) ERROR(E_NAQ); /* must be an argument */
- X esp->flag1 = 0; /* consume argument */
- X esp->op = OP_START;
- X switch (mapch_l[getcmdc(trace_sw)])
- X {
- X case 'a':
- X cond = isalpha(esp->val1);
- X break;
- X
- X case 'c':
- X cond = isalpha(esp->val1) | (esp->val1 == '$') | (esp->val1 == '.');
- X break;
- X
- X case 'd':
- X cond = isdigit(esp->val1);
- X break;
- X
- X case 'e':
- X case 'f':
- X case 'u':
- X case '=':
- X cond = !(esp->val1);
- X break;
- X
- X case 'g':
- X case '>':
- X cond = (esp->val1 > 0);
- X break;
- X
- X case 'l':
- X case 's':
- X case 't':
- X case '<':
- X cond = (esp->val1 < 0);
- X break;
- X
- X case 'n':
- X cond = esp->val1;
- X break;
- X
- X case 'r':
- X cond = isalnum(esp->val1);
- X break;
- X
- X case 'v':
- X cond = islower(esp->val1);
- X break;
- X
- X case 'w':
- X cond = isupper(esp->val1);
- X break;
- X
- X default:
- X ERROR(E_IQC);
- X }
- X if (!cond) /* if this conditional isn't satisfied */
- X {
- X for (ll = 1; ll > 0;) /* read to matching | or ' */
- X {
- X while ((skipto(0) != '"') && (skipc != '|') && (skipc != '\'')); /* skip chars */
- X if (skipc == '"') ++ll; /* start another level */
- X else if (skipc == '\'') --ll; /* end a level */
- X else if (ll == 1) break; /* "else" (|): if on this level, start executing */
- X }
- X }
- X break;
- X
- X case '\'': /* end of conditional */
- X break; /* ignore it if executing */
- X
- X case '|': /* "else" clause */
- X for (ll = 1; ll > 0;) /* skip to matching ' */
- X {
- X while ((skipto(0) != '"') && (skipc != '\'')); /* skip chars */
- X if (skipc == '"') ++ll; /* start another level */
- X else --ll; /* end a level */
- X }
- X break;
- X/* q-register numeric operations */
- X
- X case 'u':
- X if (!esp->flag1) ERROR(E_NAU); /* error if no arg */
- X else qreg[getqspec(0, getcmdc(trace_sw))].v = esp->val1;
- X esp->flag1 = esp->flag2; /* command's "value" is 2nd arg */
- X esp->val1 = esp->val2;
- X esp->flag2 = 0; /* clear 2nd arg */
- X esp->op = OP_START;
- X break;
- X
- X case 'q': /* Qn is numeric val, :Qn is # of chars, mQn is mth char */
- X mm = getqspec((colonflag || esp->flag1), getcmdc(trace_sw)); /* read register name */
- X if (!(esp->flag1))
- X {
- X esp->val1 = (colonflag) ? qreg[mm].z : qreg[mm].v;
- X esp->flag1 = 1;
- X }
- X else /* esp->flag1 is already set */
- X {
- X if ((esp->val1 >= 0) && (esp->val1 < qreg[mm].z)) /* char subscript within range? */
- X {
- X for (ll = 0, aa.p = qreg[mm].f; ll < (esp->val1 / CELLSIZE); ll++) aa.p = aa.p->f;
- X esp->val1 = (int) aa.p->ch[esp->val1 % CELLSIZE];
- X }
- X else esp->val1 = -1; /* char position out of range */
- X esp->op = OP_START; /* consume argument */
- X }
- X colonflag = 0;
- X break;
- X
- X case '%':
- X esp->val1 = (qreg[getqspec(0, getcmdc(trace_sw))].v += get_value(1)); /* add to q reg */
- X esp->flag1 = 1;
- X break;
- X/* move pointer */
- X
- X case 'c':
- X if (((tdot = dot + get_value(1)) < 0) || (tdot > z))
- X ERROR(E_POP); /* add arg to dot, default 1 */
- X else dot = tdot;
- X esp->flag2 = 0;
- X break;
- X
- X case 'r':
- X if (((tdot = dot - get_value(1)) < 0) || (tdot > z))
- X ERROR(E_POP); /* add arg to dot, default 1 */
- X else dot = tdot;
- X esp->flag2 = 0;
- X break;
- X
- X case 'j':
- X if (((tdot = get_value(0)) < 0) || (tdot > z))
- X ERROR(E_POP); /* add arg to dot, default 1 */
- X else dot = tdot;
- X esp->flag2 = 0;
- X break;
- X
- X case 'l':
- X dot += lines(get_value(1));
- X break;
- X
- X/* number of chars until nth line feed */
- X
- X case CTL (Q):
- X esp->val1 = lines(get_value(1));
- X esp->flag1 = 1;
- X break;
- X
- X/* print numeric value */
- X
- X case '=':
- X if (!esp->flag1) ERROR(E_NAE); /* error if no arg */
- X else
- X {
- X if (peekcmdc('=')) /* at least one more '=' */
- X {
- X getcmdc(trace_sw); /* read past it */
- X if (peekcmdc('=')) /* another? */
- X {
- X getcmdc(trace_sw); /* yes, read it too */
- X printf("%x", esp->val1); /* print in hex */
- X }
- X else printf("%o", esp->val1); /* print in octal */
- X }
- X else printf("%d", esp->val1);
- X if (!colonflag) crlf();
- X esp->flag1 = esp->flag2 = colonflag = 0;
- X esp->op = OP_START;
- X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
- X }
- X break;
- X/* insert text */
- X
- X case TAB: /* insert tab, then text */
- X if (ez_val & EZ_NOTABI) break; /* tab disabled */
- X if (esp->flag1) ERROR(E_IIA); /* can't have arg */
- X
- X case 'i': /* insert text at pointer */
- X term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */
- X if (esp->flag1) /* if a nI$ command */
- X {
- X if (!peekcmdc(term_char)) ERROR(E_IIA); /* next char must be term */
- X insert1(); /* first part of insert */
- X bb.p->ch[bb.c] = esp->val1 & 0177; /* insert character */
- X fwdcx(&bb); /* advance pointer and extend buffer if necessary */
- X ins_count = 1; /* save string length */
- X esp->op = OP_START; /* consume argument */
- X }
- X else /* not a nI command: insert text */
- X {
- X insert1(); /* initial insert operations */
- X
- X if (command == TAB) /* TAB insert puts in a tab first */
- X {
- X bb.p->ch[bb.c] = TAB; /* insert a tab */
- X fwdcx(&bb); /* advance pointer and maybe extend buffer */
- X }
- X moveuntil(&cptr, &bb, term_char, &ins_count, cptr.z - cptr.dot, trace_sw); /* copy cmd str -> buffer */
- X if (command == TAB) ++ins_count; /* add 1 if a tab inserted */
- X cptr.dot += ins_count; /* indicate advance over that many chars */
- X }
- X insert2(ins_count); /* finish insert */
- X getcmdc(trace_sw); /* flush terminating char */
- X colonflag = atflag = esp->flag1 = esp->flag2 = 0; /* clear args */
- X break;
- X
- X/* type text from text buffer */
- X
- X case 't':
- X for (ll = line_args(0, &aa); ll > 0; ll--) /* while there are chars to type */
- X {
- X type_char(aa.p->ch[aa.c]);
- X fwdc(&aa);
- X }
- X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
- X break;
- X
- X case 'v':
- X if ((ll = get_value(1)) > 0) /* arg must be positive */
- X {
- X mm = lines(1 - ll); /* find start */
- X nn = lines(ll) - mm; /* and number of chars */
- X set_pointer(dot + mm, &aa); /* pointer to start of text */
- X for (; nn > 0; nn--) /* as above */
- X {
- X type_char(aa.p->ch[aa.c]);
- X fwdc(&aa);
- X }
- X }
- X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
- X break;
- X/* type text from command string */
- X
- X case CTL (A):
- X term_char = (atflag) ? getcmdc(trace_sw) : CTL(A); /* set terminator */
- X while (getcmdc(0) != term_char) type_char(cmdc); /* output chars */
- X atflag = colonflag = esp->flag2 = esp->flag1 = 0;
- X esp->op = OP_START;
- X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
- X break;
- X
- X /* delete text */
- X
- X case 'd':
- X if (!esp->flag2) /* if only one argument */
- X {
- X delete1(get_value(1)); /* delete chars (default is 1) */
- X break;
- X } /* if two args, fall through to treat m,nD as m,nK */
- X
- X case 'k': /* delete lines or chars */
- X ll = line_args(1, &aa); /* aa points to start, ll chars, leave dot at beginning */
- X delete1(ll); /* delete ll chars */
- X break;
- X
- X/* q-register text loading commands */
- X
- X case CTL (U):
- X mm = getqspec(0, getcmdc(trace_sw));
- X if (!colonflag) /* X, ^U commands destroy previous contents */
- X {
- X dly_free_blist(qreg[mm].f);
- X qreg[mm].f = NULL;
- X qreg[mm].z = 0;
- X }
- X term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */
- X atflag = 0; /* clear flag */
- X
- X if ((esp->flag1) || (!peekcmdc(term_char))) /* if an arg or a nonzero insert, find register */
- X {
- X make_buffer(&qreg[mm]); /* attach a text buffer to the q register */
- X for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f); /* find end of reg */
- X bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0;
- X }
- X if (!(esp->flag1))
- X {
- X moveuntil(&cptr, &bb, term_char, &ll, cptr.z - cptr.dot, trace_sw);
- X cptr.dot += ll; /* indicate advance over that many chars */
- X qreg[mm].z += ll; /* update q-reg char count */
- X getcmdc(trace_sw); /* skip terminator */
- X }
- X else
- X {
- X if (getcmdc(trace_sw) != term_char) ERROR(E_IIA); /* must be zero length string */
- X bb.p->ch[bb.c] = esp->val1; /* store char */
- X fwdcx(&bb); /* extend the register */
- X ++qreg[mm].z;
- X esp->flag1 = 0; /* consume argument */
- X }
- X colonflag = 0;
- X break;
- X case 'x':
- X mm = getqspec(0, getcmdc(trace_sw));
- X if (!colonflag) /* X, ^U commands destroy previous contents */
- X {
- X dly_free_blist(qreg[mm].f); /* return, but delayed (in case executing now) */
- X qreg[mm].f = NULL;
- X qreg[mm].z = 0;
- X }
- X
- X if (ll = line_args(0, &aa)) /* read args and move chars, if any */
- X {
- X make_buffer(&qreg[mm]); /* attach a text buffer to the q register */
- X for (bb.p = qreg[mm].f; bb.p->f != NULL; bb.p = bb.p->f); /* find end of reg */
- X bb.c = (colonflag) ? qreg[mm].z % CELLSIZE : 0;
- X
- X movenchars(&aa, &bb, ll);
- X qreg[mm].z += ll; /* update q-reg char count */
- X }
- X colonflag = 0;
- X break;
- X
- X case 'g': /* get q register */
- X if (qreg[mm = getqspec(1, getcmdc(trace_sw))].z) /* if any chars in it */
- X {
- X cc.p = qreg[mm].f; /* point cc to start of reg */
- X cc.c = 0;
- X if (colonflag) /* :Gx types q-reg */
- X {
- X for (ll = qreg[mm].z; ll > 0; ll--)
- X {
- X type_char(cc.p->ch[cc.c]); /* type char */
- X fwdc(&cc);
- X }
- X }
- X else
- X {
- X insert1(); /* set up for insert */
- X movenchars(&cc, &bb, qreg[mm].z); /* copy q reg text */
- X insert2(qreg[mm].z); /* finish insert */
- X }
- X }
- X colonflag = 0;
- X break;
- X/* q-register push and pop */
- X
- X case '[':
- X if (qsp > &qstack[QSTACKSIZE-1]) ERROR(E_PDO); /* stack full */
- X else
- X {
- X make_buffer(++qsp); /* increment stack ptr and put a text buffer there */
- X mm = getqspec(1, getcmdc(trace_sw)); /* get the q reg name */
- X
- X aa.p = qreg[mm].f; /* point to the q register */
- X aa.c = 0;
- X bb.p = qsp->f; /* point to the new list */
- X bb.c = 0;
- X movenchars(&aa, &bb, qreg[mm].z); /* copy the text */
- X qsp->z = qreg[mm].z; /* and the length */
- X qsp->v = qreg[mm].v; /* and the value */
- X }
- X break;
- X
- X case ']':
- X mm = getqspec(1, getcmdc(trace_sw)); /* get reg name */
- X if (qsp < &qstack[0]) /* if stack empty */
- X {
- X if (colonflag) /* :] returns 0 */
- X {
- X esp->flag1 = 1;
- X esp->val1 = 0;
- X colonflag = 0;
- X }
- X else ERROR(E_CPQ); /* ] makes an error */
- X }
- X else /* stack not empty */
- X {
- X free_blist(qreg[mm].f); /* return orig contents of reg */
- X qreg[mm].f = qsp->f; /* substitute stack entry */
- X qsp->f->b = (struct buffcell *) &qreg[mm];
- X qsp->f = NULL; /* null out stack entry */
- X qreg[mm].z = qsp->z;
- X qreg[mm].v = qsp->v;
- X if (colonflag)
- X {
- X esp->flag1 = 1; /* :] returns -1 */
- X esp->val1 = -1;
- X colonflag = 0;
- X }
- X --qsp;
- X }
- X break;
- X case '\\':
- X if (!(esp->flag1)) /* no argument; read number */
- X {
- X ll = esp->val1 = 0; /* sign flag and initial value */
- X for (ctrl_s = 0; dot <= z; dot++, ctrl_s--) /* count digits; don't read beyond buffer */
- X {
- X set_pointer(dot, &aa); /* point to dot */
- X if ((aa.p->ch[aa.c] == '+') || (aa.p->ch[aa.c] == '-'))
- X {
- X if (ll) break; /* second sign: quit */
- X else ll = aa.p->ch[aa.c]; /* first sign: save it */
- X }
- X else
- X {
- X if (ctrl_r != 16) /* octal or decimal */
- X { /* stop if not a valid digit */
- X if ((!isdigit(aa.p->ch[aa.c])) || (aa.p->ch[aa.c] - '0' >= ctrl_r)) break;
- X esp->val1 = esp->val1 * ctrl_r + (aa.p->ch[aa.c] - '0');
- X }
- X else
- X {
- X if (!isxdigit(aa.p->ch[aa.c])) break;
- X esp->val1 = esp->val1 * 16 + ( (isdigit(aa.p->ch[aa.c])) ?
- X aa.p->ch[aa.c] - '0' : mapch_l[aa.p->ch[aa.c]] - 'a' + 10);
- X } /* end of hex */
- X } /* end of digit processing */
- X } /* end of "for each char" */
- X if (ll == '-') esp->val1 = -(esp->val1); /* if minus sign */
- X esp->flag1 = 1; /* always returns a value */
- X }
- X
- X else /* argument: insert it as a digit string */
- X {
- X if (ctrl_r == 8) sprintf(t_bcell.ch, "%o", esp->val1); /* print as digits */
- X else if (ctrl_r == 10) sprintf(t_bcell.ch, "%d", esp->val1);
- X else sprintf(t_bcell.ch, "%x", esp->val1);
- X insert1(); /* start insert */
- X cc.p = &t_bcell; /* point cc to the temp cell */
- X cc.c = 0;
- X moveuntil(&cc, &bb, '\0', &ins_count, CELLSIZE-1, 0); /* copy the char string */
- X insert2(ins_count); /* finish the insert */
- X esp->flag1 = 0; /* consume argument */
- X esp->op = OP_START;
- X }
- X break;
- X case CTL (T): /* type or input character */
- X if (esp->flag1) /* type */
- X {
- X type_char(esp->val1);
- X esp->flag1 = 0;
- X if (!WN_scroll) window(WIN_REDRAW); /* if not in scroll mode, force full redraw on next refresh */
- X }
- X else
- X {
- X esp->val1 = (et_val & ET_NOWAIT) ? gettty_nowait() : gettty();
- X if (!(et_val & ET_NOECHO) && (esp->val1 > 0) && !inp_noterm) type_char(esp->val1); /* echo */
- X esp->flag1 = 1;
- X }
- X break;
- X
- X/* search commands */
- X
- X case 's': /* search within buffer */
- X build_string(&sbuf); /* read the search string */
- X end_search ( do_search( setup_search() ) ); /* search */
- X break;
- X
- X case 'n': /* search through rest of file */
- X case '_':
- X do_nsearch(command); /* call routine for N, _, E_ */
- X break;
- X
- X case 'o': /* branch to tag */
- X do_o();
- X break;
- X/* file I/O commands */
- X
- X case 'p': /* write a page, get next (ignore args for now) */
- X if (esp->flag1 && esp->flag2) /* if two args */
- X write_file(&aa, line_args(0, &aa), 0); /* write spec'd buffer with no FF */
- X else /* one arg */
- X {
- X for (ll = get_value(1); ll > 0; ll--) /* get count and loop */
- X {
- X set_pointer(0, &aa);
- X if (peekcmdc('w')) write_file(&aa, z, 1); /* PW writes buffer, then FF */
- X else
- X {
- X write_file(&aa, z, ctrl_e); /* P writes buffer, FF if read in, then gets next page */
- X dot = z = 0; /* empty the buffer */
- X set_pointer(0, &aa); /* set a pointer to the beginning of the buffer */
- X buff_mod = 0; /* mark where new buffer starts */
- X esp->val1 = read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) ); /* read a page */
- X esp->flag1 = colonflag;
- X }
- X }
- X }
- X if (peekcmdc('w')) getcmdc(trace_sw); /* if a PW command, consume the W */
- X colonflag = 0;
- X break;
- X
- X case 'y': /* get a page into buffer */
- X if (esp->flag1) ERROR(E_NYA);
- X if ((z) && (!(ed_val & ED_YPROT))) ERROR(E_YCA); /* don't lose text */
- X dot = z = 0; /* clear buffer */
- X set_pointer(0, &aa); /* set a pointer to the beginning of the buffer */
- X buff_mod = 0; /* mark where new buffer starts */
- X read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) ); /* read a page */
- X esp->flag1 = colonflag;
- X esp->op = OP_START;
- X colonflag = 0;
- X break;
- X case 'a': /* append, or ascii value */
- X if (esp->flag1 && !colonflag) /* ascii value */
- X {
- X ll = dot + esp->val1; /* set a pointer before addr'd char */
- X if ((ll >= 0) && (ll < z)) /* if character lies within buffer */
- X {
- X set_pointer(ll, &aa);
- X esp->val1 = (int) aa.p->ch[aa.c]; /* get char (flag already set) */
- X }
- X else esp->val1 = -1; /* otherwise return -1 */
- X }
- X else
- X {
- X set_pointer(z, &aa); /* set pointer to end of buffer */
- X if (z < buff_mod) buff_mod = z; /* mark where new buffer starts */
- X if (esp->flag1 && (esp->val1 <= 0)) ERROR(E_IAA); /* neg or 0 arg to :A */
- X read_file(&aa, &z, (esp->flag1 ? esp->val1 : 0) ); /* read a page */
- X esp->flag1 = colonflag;
- X colonflag = 0;
- X }
- X esp->op = OP_START;
- X break;
- X
- X/* window commands */
- X
- X case 'w':
- X do_window(0); /* this stuff is with the window driver */
- X break;
- X
- X case CTL (W):
- X do_window(1); /* this is, too */
- X break;
- X
- X default:
- X ERROR(E_ILL); /* invalid command */
- X
- X } /* end of "switch" */
- X return; /* normal exit */
- X } /* end of exec_cmds1 */
- X
- END_OF_te_exec1.c
- if test 21012 -ne `wc -c <te_exec1.c`; then
- echo shar: \"te_exec1.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"te_exec2.c\" \(29256 characters\)
- if test -f te_exec2.c ; then
- echo shar: Will not over-write existing file \"te_exec2.c\"
- else
- sed "s/^X//" >te_exec2.c <<'END_OF_te_exec2.c'
- X/* TECO for Ultrix Copyright 1986 Matt Fichtenbaum */
- X/* This program and its components belong to GenRad Inc, Concord MA 01742 */
- X/* They may be copied if this copyright notice is included */
- X
- X/* te_exec2.c process "E" and "F" commands 2/26/87 */
- X#include "te_defs.h"
- X#include <sys/wait.h>
- X
- Xstruct qh oldcstring; /* hold command string during ei */
- X
- X/* file stuff for input/output files */
- X
- Xstruct infiledata pi_file = { NULL, -1 }; /* input files */
- Xstruct infiledata si_file = { NULL, -1 };
- Xstruct infiledata *infile = &pi_file; /* pointer to currently active input file structure */
- Xstruct outfiledata po_file, so_file; /* output files */
- Xstruct outfiledata *outfile = &po_file; /* pointer to currently active output file structure */
- XFILE *eisw; /* indirect command file pointer */
- X
- X/* process E commands */
- X
- Xdo_e()
- X {
- X char c; /* temps */
- X int old_var;
- X FILE *t_eisw;
- X
- X switch (mapch_l[getcmdc(trace_sw)]) /* read next character and dispatch */
- X {
- X
- X/* numeric values */
- X
- X case 'd': /* ED */
- X set_var(&ed_val);
- X break;
- X
- X case 's': /* ES */
- X set_var(&es_val);
- X break;
- X
- X case 't': /* ET */
- X old_var = et_val;
- X set_var(&et_val);
- X et_val = (et_val & 0100651) | 001006; /* force read_only bits */
- X if ((et_val ^ old_var) & ET_TRUNC) window(WIN_REDRAW); /* redraw if ET & 256 changes */
- X break;
- X
- X case 'u': /* EU */
- X set_var(&eu_val);
- X break;
- X
- X case 'v': /* EV */
- X set_var(&ev_val);
- X break;
- X
- X case 'z': /* EZ */
- X old_var = ez_val;
- X set_var(&ez_val);
- X tabmask = (ez_val & EZ_TAB4) ? 3 : 7; /* set tab mask */
- X if ((ez_val ^ old_var) & EZ_TAB4) window(WIN_REDRAW); /* force window redisplay if EZ_TAB4 changes */
- X break;
- X/* E_ search */
- X
- X case '_':
- X do_nsearch('e');
- X break;
- X
- X/* file I/O commands */
- X
- X case 'a': /* set secondary output */
- X outfile = &so_file;
- X break;
- X
- X case 'b': /* open read/write with backup */
- X if (!read_filename(1, 'r')) ERROR(E_NFI); /* read the name */
- X if (infile->fd) fclose(infile->fd); /* close previously-open file */
- X if (!(infile->fd = fopen(fbuf.f->ch, "r")))
- X {
- X if (!colonflag) ERROR(E_FNF);
- X }
- X else
- X {
- X if (outfile->fd) ERROR(E_OFO); /* output file already open */
- X for (ll = 0; ll < CELLSIZE; ll++) /* save file string */
- X if ((outfile->t_name[ll] = outfile->f_name[ll] = fbuf.f->ch[ll]) == '\0') break;
- X outfile->name_size = ll;
- X outfile->t_name[ll++] = '.';
- X outfile->t_name[ll++] = 't';
- X outfile->t_name[ll++] = 'm';
- X outfile->t_name[ll++] = 'p';
- X outfile->t_name[ll] = '\0';
- X if (!(outfile->fd = fopen(outfile->t_name, "w"))) ERROR(E_COF);
- X outfile->bak = 1; /* set backup mode */
- X }
- X infile->eofsw = -1 - (esp->val1 = (infile->fd) ? -1 : 0);
- X esp->flag1 = colonflag;
- X colonflag = 0;
- X break;
- X
- X case 'x': /* finish edit and exit */
- X exitflag = -1;
- X
- X /* --- fall through to "EC" --- */
- X
- X case 'c': /* finish edit */
- X set_pointer(0, &aa); /* set a pointer to start of text buffer */
- X write_file(&aa, z, ctrl_e); /* write the current buffer */
- X dot = z = 0; /* empty the buffer */
- X window(WIN_REDRAW); /* force window redraw */
- X if ((outfile->fd) && (infile->fd) && !(infile->eofsw)) /* if any input remaining, copy it to output */
- X while ((c = getc(infile->fd)) != EOF) putc(c, outfile->fd);
- X
- X /* --- fall through to "EF" --- */
- X case 'f': /* close output file */
- X if (outfile->fd) /* only if one is open */
- X {
- X fclose(outfile->fd);
- X if (outfile->bak & 1) /* if this is "backup" mode */
- X {
- X outfile->f_name[outfile->name_size] = '.';
- X outfile->f_name[outfile->name_size+1] = 'b';
- X outfile->f_name[outfile->name_size+2] = 'a';
- X outfile->f_name[outfile->name_size+3] = 'k';
- X outfile->f_name[outfile->name_size+4] = '\0';
- X outfile->t_name[outfile->name_size] = '\0';
- X rename(outfile->t_name, outfile->f_name); /* rename orig file */
- X }
- X
- X if (!(outfile->bak & 8)) /* if output file had ".tmp" extension */
- X { /* remove it */
- X outfile->t_name[outfile->name_size] = '.';
- X outfile->f_name[outfile->name_size] = '\0';
- X rename(outfile->t_name, outfile->f_name); /* rename output */
- X }
- X }
- X outfile->fd = NULL; /* mark "no output file open" */
- X break;
- X
- X case 'i': /* indirect file execution */
- X if (!read_filename(1, 'i')) /* if no filename specified, reset command input */
- X {
- X if (eisw) /* if ending a file execute, restore the previous "old command string" */
- X {
- X fclose(eisw); /* return the file descriptor */
- X dly_free_blist(cbuf.f); /* return the command string used by the file (after execution done) */
- X cbuf.f = oldcstring.f;
- X cbuf.z = oldcstring.z;
- X }
- X t_eisw = 0;
- X }
- X else if (!(t_eisw = fopen(fbuf.f->ch, "r")))
- X {
- X if (!colonflag) ERROR(E_FNF);
- X }
- X else if (!eisw) /* if this "ei" came from the command string */
- X {
- X oldcstring.f = cbuf.f; /* save current command string */
- X oldcstring.z = cbuf.z;
- X cbuf.f = NULL; /* and make it inaccessible to "rdcmd" */
- X }
- X if (eisw) fclose(eisw); /* if a command file had been open, close it */
- X esp->val1 = (eisw = t_eisw) ? -1 : 0;
- X esp->flag1 = colonflag;
- X colonflag = 0;
- X esp->op = OP_START;
- X break;
- X case 'k': /* kill output file */
- X kill_output(outfile);
- X break;
- X
- X case 'p': /* switch to secondary input */
- X infile = &si_file;
- X break;
- X
- X case 'r': /* specify input file, or switch to primary input */
- X if (!read_filename(0, 'r')) infile = &pi_file; /* no name, switch to primary input */
- X else
- X {
- X if (infile->fd) fclose(infile->fd); /* close previously-open file */
- X if (!(infile->fd = fopen(fbuf.f->ch, "r")))
- X {
- X if (!colonflag) ERROR(E_FNF);
- X }
- X }
- X infile->eofsw = -1 - (esp->val1 = (infile->fd) ? -1 : 0);
- X esp->flag1 = colonflag;
- X colonflag = 0;
- X esp->op = OP_START;
- X break;
- X
- X case 'w': /* specify output file, or switch to primary output */
- X if(!read_filename(0, 'w')) outfile = &po_file;
- X else
- X {
- X if (outfile->fd) ERROR(E_OFO); /* output file already open */
- X for (ll = 0; ll < CELLSIZE; ll++) /* save file string */
- X if ((outfile->t_name[ll] = outfile->f_name[ll] = fbuf.f->ch[ll]) == '\0') break;
- X outfile->name_size = ll;
- X if (!(ez_val & EZ_NOTMPFIL)) /* if not using literal output name */
- X {
- X outfile->t_name[ll++] = '.'; /* use provisional suffix ".tmp" */
- X outfile->t_name[ll++] = 't';
- X outfile->t_name[ll++] = 'm';
- X outfile->t_name[ll++] = 'p';
- X outfile->t_name[ll] = '\0';
- X }
- X if (!(outfile->fd = fopen(outfile->t_name, "w"))) ERROR(E_COF);
- X outfile->bak = ez_val & EZ_NOTMPFIL; /* save "temp suffix" status */
- X }
- X break;
- X
- X case 'y': /* EY is Y without protection */
- X if (esp->flag1) ERROR(E_NYA);
- X dot = z = 0; /* clear buffer */
- X set_pointer(0, &aa);
- X read_file(&aa, &z, (ed_val & ED_EXPMEM ? -1 : 0) );
- X esp->flag1 = colonflag;
- X colonflag = 0;
- X esp->op = OP_START;
- X break;
- X case 'n': /* wildcard filespec */
- X esp->val1 = do_en();
- X esp->flag1 = colonflag;
- X colonflag = 0;
- X esp->op = OP_START;
- X break;
- X
- X case 'q': /* system command */
- X esp->val1 = do_eq(); /* do this as a separate routine */
- X esp->flag1 = colonflag;
- X colonflag = 0;
- X esp->op = OP_START;
- X break;
- X
- X default:
- X ERROR(E_IEC);
- X }
- X }
- X/* routine to execute a system command */
- X/* this is done by forking off another process */
- X/* to execute a shell via 'execl' */
- X/* routine returns -1 if success, 0 if error in fork */
- X
- Xint do_eq()
- X {
- X int t;
- X union wait status;
- X char *pname; /* pointer to name of shell */
- X extern char *getenv();
- X
- X build_string(&sysbuf);
- X if (sysbuf.z > CELLSIZE-2) ERROR(E_STL); /* command must fit within one cell */
- X sysbuf.f->ch[sysbuf.z] = '\0'; /* store terminating null */
- X if (!(pname = getenv("SHELL"))) ERROR(E_SYS); /* read shell name */
- X
- X if (!esp->flag1) /* if not m,nEQ command */
- X {
- X if (win_data[7]) window(WIN_SUSP); /* restore full screen */
- X crlf(); /* force characters out */
- X setup_tty(TTY_SUSP); /* restore terminal to normal mode */
- X
- X t = vfork(); /* fork a new process */
- X if (t == 0) /* if this is the child */
- X {
- X execl(pname, pname, "-c", &sysbuf.f->ch[0], 0); /* call the named Unix routine */
- X printf("Error in 'execl'\n"); /* normally shouldn't get here */
- X exit(1);
- X }
- X
- X while (wait(&status) != t); /* if parent, wait for child to finish */
- X if (status.w_retcode) t = -1; /* keep failure indication from child */
- X
- X setup_tty(TTY_RESUME); /* restore terminal to teco mode */
- X if (win_data[7]) /* if window was enabled */
- X {
- X vt(VT_SETSPEC1); /* set reverse video */
- X fputs("Type RETURN to continue", stdout); /* require CR before continuing */
- X vt(VT_CLRSPEC); /* reverse video off */
- X while (gettty() != LF);
- X putchar(CR); /* back to beginning of line */
- X vt(VT_EEOL); /* and erase the message */
- X window(WIN_RESUME); /* re-enable window */
- X window(WIN_REDRAW); /* and make it redraw afterwards */
- X }
- X }
- X
- X else t = do_eq1(pname); /* m,nEQ command */
- X
- X return( (t == -1) ? 0 : -1); /* return failure if fork failed or proc status nonzero */
- X }
- X/* Execute m,nEQtext$ command. Run "text" as a Unix command that */
- X/* receives its std input from chars m through n of teco's buffer. */
- X/* Output from the command is placed in Q#. */
- X
- Xint do_eq1(shell)
- X char *shell; /* arg is pointer to shell name */
- X {
- X int ff, pipe_in[2], pipe_out[2]; /* fork result and two pipes */
- X FILE *xx_in, *xx_out; /* std in and out for called process */
- X FILE *fdopen();
- X union wait status;
- X
- X ll = line_args(1, &aa); /* set aa to start of text, ll to number of chars */
- X dot += ll; /* set pointer at end of text */
- X ctrl_s = -ll; /* set ^S to - # of chars */
- X
- X if (pipe(pipe_out)) ERROR(E_SYS); /* make input pipe; failure if can't */
- X
- X if (win_data[7]) window(WIN_SUSP); /* disable split screen */
- X setup_tty(TTY_SUSP); /* put console back to original state */
- X if ((ff = fork()) == -1) /* fork first child: if error, quit */
- X {
- X close(pipe_out[0]);
- X close(pipe_out[1]);
- X setup_tty(TTY_RESUME);
- X if (win_data[7]) window(WIN_RESUME), window(WIN_REDRAW);
- X ERROR(E_SYS);
- X }
- X
- X if (ff) /* if this is the parent, the task is to read into q# */
- X {
- X make_buffer(&timbuf); /* initialize the q# header */
- X bb.p = timbuf.f; /* init bb to point to q# */
- X timbuf.z = bb.c = 0;
- X
- X close(pipe_out[1]); /* parent won't write to this pipe */
- X
- X if ((xx_out = fdopen(pipe_out[0], "r")) == 0) /* open the "std out" pipe for reading */
- X {
- X close(pipe_out[0]); /* if can't open output pipe */
- X setup_tty(TTY_RESUME);
- X if (win_data[7]) window(WIN_RESUME), window(WIN_REDRAW);
- X ERROR(E_SYS); /* "open" failure */
- X }
- X read_stream(xx_out, 0, &bb, &timbuf.z, 0, 0, 1); /* read from pipe to q# */
- X close(pipe_out[0]);
- X
- X while (wait(&status) != ff); /* wait for children to finish */
- X setup_tty(TTY_RESUME);
- X if (win_data[7]) window(WIN_RESUME), window(WIN_REDRAW);
- X return(status.w_retcode ? -1 : 0);
- X }
- X/* This is the child. It in turn forks into two processes, of which the "parent" */
- X/* (original child) writes the specified part of the buffer to the pipe, and the */
- X/* new child (grandchild to the original teco) execl's the Unix command. */
- X
- X else /* this is the child */
- X {
- X close(pipe_out[0]); /* won't read from "output" pipe */
- X if (pipe(pipe_in)) exit(1); /* make the "std in" pipe for the process, quit if can't */
- X
- X if ((ff = fork()) == -1) exit(1); /* fork to two processes (total 3), exit if error */
- X
- X if (ff) /* parent - will send chars */
- X {
- X close(pipe_in[0]); /* won't read from this pipe */
- X
- X /* open pipe for writing; exit if open fails */
- X
- X if ((xx_in = fdopen(pipe_in[1], "w")) == 0) exit(1);
- X
- X write_stream(xx_in, &aa, ll, 0); /* write to stream, CRLF becomes LF */
- X fclose(xx_in);
- X
- X while (wait(&status) != ff); /* wait for child */
- X exit(status.w_retcode); /* exit with child's status */
- X }
- X
- X else /* this process is the grandchild */
- X {
- X close(pipe_in[1]); /* close "input" for writing */
- X dup2(pipe_in[0], fileno(stdin)); /* substitute pipe_in for stdin */
- X dup2(pipe_out[1], fileno(stdout)); /* and pipe_out for stdout */
- X close(pipe_in[0]); /* close original descriptors */
- X close(pipe_out[1]);
- X
- X execl(shell, shell, "-c", &sysbuf.f->ch[0], 0); /* execute specified routine */
- X fputs("execl failed\n", stderr);
- X exit(1);
- X }
- X }
- X }
- X/* Routines to handle EN wild-card file specification */
- X/* ENfilespec$ defines file class, leaving 'filespec' */
- X/* in filespec buffer and reading expanded list of */
- X/* files into local buffer. EN$ gets next filespec */
- X/* into filespec buffer. */
- X
- Xstruct qh en_buf; /* header for storage for file list */
- Xstruct qp en_ptr; /* pointer to load/read file list */
- Xstatic char glob_cmd0[] = { 'g', 'l', 'o', 'b', ' ' } ;
- X
- Xint do_en()
- X {
- X int t;
- X
- X if (build_string(&fbuf)) /* if a file string is specified */
- X {
- X if (fbuf.z > CELLSIZE-2) ERROR(E_STL); /* upper limit on string length */
- X fbuf.f->ch[fbuf.z] = '\0'; /* terminating null */
- X t = do_glob(&en_buf); /* glob the result */
- X en_ptr.p = en_buf.f; /* set the buffer pointer to the beginning of the buffer */
- X en_ptr.dot = en_ptr.c = 0;
- X }
- X else /* if no string, get next filename */
- X {
- X do_en_next();
- X t = (fbuf.z) ? -1 : 0; /* t zero if no more filespecs */
- X if (!t && !colonflag) ERROR(E_NFI); /* if no colon, end of spec is an error */
- X }
- X return (t);
- X }
- X
- X/* routine to expand the string in the filespec buffer */
- X/* argument is the address of a qh that gets the expanded string */
- X/* argument->v gets set to the number of file specs found */
- X
- Xint do_glob(buff)
- X struct qh *buff;
- X {
- X char glob_cmd[CELLSIZE+5]; /* "glob filespec" command string */
- X int t;
- X char c;
- X int glob_pipe[2]; /* pipe to forked shell for expanding filenames */
- X struct qp glob_ptr; /* pointer for loading result buffer */
- X FILE *xx_out; /* stream for reading chars from pipe */
- X FILE *fdopen();
- X union wait status;
- X
- X make_buffer(buff); /* initialize expanded file buffer */
- X glob_ptr.p = buff->f; /* initialize pointer to buffer */
- X glob_ptr.c = glob_ptr.dot = buff->z = buff->v = 0;
- X for (t = 0; t < 5; t++) glob_cmd[t] = glob_cmd0[t]; /* set up "glob filespec" command */
- X for (t = 0; t < fbuf.z +1; t++) glob_cmd[t+5] = fbuf.f->ch[t];
- X
- X if (pipe(glob_pipe)) ERROR(E_SYS); /* make a pipe */
- X setup_tty(TTY_SUSP); /* put console back to normal */
- X if ((t = fork()) == -1) /* spawn a child... if failure */
- X {
- X close(glob_pipe[0]); /* undo the pipe */
- X close(glob_pipe[1]);
- X setup_tty(TTY_RESUME);
- X ERROR(E_SYS); /* and exit with failure */
- X }
- X
- X if (t) /* if this is the parent */
- X {
- X close(glob_pipe[1]); /* parent won't write */
- X if ((xx_out = fdopen(glob_pipe[0], "r")) == 0) /* open pipe for read */
- X {
- X close(glob_pipe[0]); /* failure to open */
- X setup_tty(TTY_RESUME);
- X ERROR(E_SYS);
- X }
- X
- X while ((c = getc(xx_out)) != EOF) /* read characters from pipe */
- X {
- X if (c == '\0') ++buff->v; /* count null chars that separate file specs */
- X glob_ptr.p->ch[glob_ptr.c] = c; /* store them in buffer */
- X fwdcx(&glob_ptr);
- X }
- X
- X fclose(xx_out); /* through with stream */
- X buff->z = glob_ptr.dot; /* save character count */
- X while (wait(&status) != t); /* wait for child to finish */
- X setup_tty(TTY_RESUME);
- X return(status.w_retcode ? 0 : -1); /* return success unless child exited nonzero */
- X }
- X else /* this is the child */
- X {
- X close(glob_pipe[0]); /* child won't read */
- X dup2(glob_pipe[1], fileno(stdout)); /* substitute pipe for standard out */
- X close(glob_pipe[1]); /* don't need that anymore */
- X execl("/bin/csh", "csh", "-fc", glob_cmd, 0); /* execute the "glob" */
- X fputs("execl failed\n", stderr);
- X exit(1);
- X }
- X }
- X
- X/* routine to get next file spec from "EN" list into filespec buffer */
- X
- Xdo_en_next()
- X {
- X char c;
- X
- X make_buffer(&fbuf); /* initialize the filespec buffer */
- X fbuf.z = 0;
- X
- X while(en_ptr.dot < en_buf.z) /* stop at end of string */
- X {
- X c = en_ptr.p->ch[en_ptr.c];
- X fwdc(&en_ptr);
- X if (!c) break; /* null is terminator between file specs */
- X fbuf.f->ch[fbuf.z++] = c; /* store char */
- X if (fbuf.z >= CELLSIZE-1) ERROR(E_STL); /* limit on filespec size */
- X }
- X
- X fbuf.f->ch[fbuf.z] = '\0'; /* filespec ends with NULL */
- X }
- X
- X/* routine to read a file name */
- X/* reads it into fbuf text area */
- X/* returns nonzero if a name, 0 if none */
- X/* flag nonzero => empty name clears filespec buffer */
- X/* func is 'r' for ER or EB cmds, 'i' for EI, 'w' for EW */
- X
- Xint read_filename(flag, func)
- X int flag;
- X char func;
- X {
- X int i, t, expand;
- X char c;
- X struct qh temp_buff; /* temp buffer for globbing filespec */
- X
- X if (!(t = build_string(&fbuf))) /* if no name spec'd */
- X {
- X if (flag) fbuf.z = 0; /* if no name spec'd, set length to 0 */
- X }
- X else
- X {
- X if (fbuf.z > CELLSIZE-2) ERROR(E_STL);
- X fbuf.f->ch[fbuf.z] = '\0'; /* store terminating NULL */
- X
- X/* check for characters to be expanded by the shell */
- X
- X for (i = 0; i < fbuf.z; i++)
- X if ((c = fbuf.f->ch[i]) == '*' || c == '?' || c == '[' || c == 0173) break;
- X if ( (expand = (i < fbuf.z)) || fbuf.f->ch[0] == '~') /* one of these was found, or first char is ~ */
- X {
- X temp_buff.f = NULL; /* make a temp buffer to glob filename into */
- X make_buffer(temp_buff);
- X do_glob(&temp_buff); /* expand the file name */
- X if (temp_buff.z == 0) /* no match */
- X {
- X free_blist(temp_buff.f); /* return the storage */
- X ERROR(func == 'w' ? E_COF : E_FNF); /* "can't open" or "file not found" */
- X }
- X else if (temp_buff.v == 0) /* if exactly one file name */
- X {
- X free_blist(fbuf.f); /* return the old file spec */
- X fbuf.f = temp_buff.f; /* put the temp buffer there instead */
- X fbuf.z = temp_buff.z;
- X if (fbuf.z > CELLSIZE-2) ERROR(E_STL);
- X fbuf.f->ch[fbuf.z] = '\0';
- X
- X if (func == 'w' && expand) /* if this is EW and 'twas from a wildcard expansion */
- X {
- X vt(VT_SETSPEC1); /* "file XXXX already exists: overwrite? [yn]" */
- X fputs("File ", stdout);
- X fputs(fbuf.f->ch, stdout);
- X fputs(" already exists: overwrite? [ny] ", stdout);
- X vt(VT_CLRSPEC);
- X c = gettty(); /* read user's response */
- X putchar(CR);
- X vt(VT_EEOL); /* clean up the screen */
- X if (c != 'y') ERROR(E_COF); /* abort here */
- X }
- X }
- X
- X else /* multiple file specs */
- X {
- X if (func != 'r' || !(ez_val & EZ_MULT)) /* if multiple file specs here aren't allowed */
- X {
- X free_blist(temp_buff.f); /* return the storage */
- X ERROR(E_AMB);
- X }
- X free_blist(en_buf.f); /* substitute the expansion for the "EN" list */
- X en_ptr.p = en_buf.f = temp_buff.f; /* and initialize the "EN" list pointer */
- X en_buf.z = temp_buff.z;
- X en_ptr.dot = en_ptr.c = 0;
- X do_en_next(); /* get the first file */
- X }
- X }
- X }
- X return(t);
- X }
- X
- X
- X
- X/* fetch or set variable */
- X
- Xset_var(arg)
- X int *arg; /* argument is pointer to variable */
- X {
- X if (esp->flag1) /* if an argument, then set the variable */
- X {
- X if (esp->flag2) /* if two arguments, then <clr>, <set> */
- X *arg = (*arg & ~esp->val2) | esp->val1;
- X else *arg = esp->val1; /* one arg is new value */
- X esp->flag2 = esp->flag1 = 0; /* consume argument */
- X }
- X else /* otherwise fetch the variable's value */
- X {
- X esp->val1 = *arg;
- X esp->flag1 = 1;
- X }
- X }
- X
- X
- X
- X/* read from selected input file stream into specified buffer */
- X/* terminate on end-of-file or form feed */
- X/* if endsw > 0 terminates after that many lines */
- X/* if endsw < 0 stops if z > BUFF_LIMIT */
- X/* returns -1 if read EOF, 0 otherwise */
- X
- Xint read_file(buff, nchars, endsw)
- X struct qp *buff;
- X int *nchars, endsw;
- X {
- X if (!infile->fd) infile->eofsw = -1, ctrl_e = 0; /* return if no input file open */
- X else infile->eofsw = read_stream(infile->fd, &ctrl_e, buff, nchars, endsw, ez_val & EZ_CRLF, ez_val & EZ_READFF);
- X return(esp->val1 = infile->eofsw);
- X }
- X/* read from an I/O stream into specified buffer */
- X/* this is used by read_file and by "eq" pipe from other Unix processes */
- X/* args buff, nchars, endsw as above; file is stream pointer, ff_found is */
- X/* address of a switch to set if read ended with a FF, crlf_sw is lf->crlf */
- X/* conversion, ff_sw indicates whether to stop on a form feed. */
- X
- Xint read_stream(file, ff_found, buff, nchars, endsw, crlf_sw, ff_sw)
- X FILE *file;
- X struct qp *buff;
- X int *ff_found, *nchars, endsw, crlf_sw, ff_sw;
- X {
- X char chr;
- X int crflag;
- X register struct buffcell *p;
- X register int c;
- X
- X p = (*buff).p; /* copy pointer locally */
- X c = (*buff).c;
- X crflag = 0; /* "last char wasn't CR" */
- X while (((chr = getc(file)) != EOF) && ((chr != FF) || ff_sw))
- X {
- X if ((chr == LF) && !crflag && !crlf_sw) /* automatic cr before lf */
- X {
- X p->ch[c] = CR; /* store a cr */
- X ++(*nchars); /* increment buffer count */
- X if (++c > CELLSIZE-1) /* next cell? */
- X {
- X if (!p->f) /* need a new cell? */
- X {
- X p->f = get_bcell();
- X p->f->b = p;
- X }
- X p = p->f;
- X c = 0;
- X }
- X }
- X p->ch[c] = chr; /* store char */
- X ++(*nchars); /* increment character count */
- X if (++c > CELLSIZE-1) /* next cell? */
- X {
- X if (!p->f) /* need a new cell? */
- X {
- X p->f = get_bcell();
- X p->f->b = p;
- X }
- X p = p->f;
- X c = 0;
- X }
- X crflag = (chr == CR); /* flag set if last char was CR */
- X if ((chr == LF) && ((endsw < 0 && z > BUFF_LIMIT) || (endsw > 0 && --endsw == 0))) break; /* term after N lines */
- X }
- X (*buff).p = p; /* update pointer */
- X (*buff).c = c;
- X if (ff_found) *ff_found = (chr == FF) ? -1 : 0; /* set flag to indicate whether FF found */
- X return( (chr == EOF) ? -1 : 0); /* and return "eof found" value */
- X }
- X/* routine to write text buffer out to selected output file */
- X/* arguments are qp to start of text, number of characters, */
- X/* and an "append FF" switch */
- X
- Xwrite_file(buff, nchars, ffsw)
- X struct qp *buff;
- X int nchars, ffsw;
- X {
- X if (!outfile->fd && (nchars)) ERROR(E_NFO);
- X else write_stream(outfile->fd, buff, nchars, ez_val & EZ_CRLF);
- X if (outfile->fd && ffsw) putc(FF, outfile->fd);
- X }
- X
- X
- X/* routine to write text buffer to I/O stream. Used by */
- X/* write_file, above, and by "eq" write to pipe to other */
- X/* Unix processes. Arguments buff, nchars as above; file */
- X/* is stream pointer, crlf_sw zero converts CRLF to LF */
- X
- Xwrite_stream(file, buff, nchars, crlf_sw)
- X FILE *file;
- X struct qp *buff;
- X int nchars, crlf_sw;
- X {
- X char c;
- X int crflag;
- X
- X crflag = 0;
- X for (; nchars > 0; nchars--)
- X {
- X if ((c = (*buff).p->ch[(*buff).c]) == CR) crflag = 1; /* set flag if a c.r. */
- X else
- X {
- X if ((crflag) && ((c != LF) || crlf_sw)) /* if c.r. not before lf, or if not in */
- X putc(CR, file); /* "no cr" mode, output the c.r. */
- X crflag = 0;
- X putc(c, file);
- X }
- X if (++(*buff).c > CELLSIZE-1)
- X {
- X (*buff).p = (*buff).p->f;
- X (*buff).c = 0;
- X }
- X }
- X }
- X
- X
- X/* routine to kill output file: argument is pointer to an output file structure */
- X
- Xkill_output(outptr)
- X struct outfiledata *outptr;
- X {
- X if (outptr->fd)
- X {
- X fclose(outptr->fd);
- X unlink(outptr->t_name);
- X outptr->fd = NULL;
- X }
- X }
- X/* "panic" routine called when "hangup" signal occurs */
- X/* this routine saves the text buffer and closes the output files */
- X
- Xchar panic_name[] = "TECO_SAVED.tmp"; /* name of file created to save buffer */
- X
- Xpanic()
- X {
- X if (!outfile->fd && z) outfile->fd = fopen(panic_name, "w"); /* if buffer nonempty and no file open, make one */
- X
- X set_pointer(0, &aa); /* set a pointer to start of text buffer */
- X if (outfile->fd && z) write_file(&aa, z, 0); /* and write out buffer unless "open" failed */
- X
- X if (po_file.fd) fclose(po_file.fd), po_file.fd = NULL; /* close any open output files */
- X if (so_file.fd) fclose(so_file.fd), so_file.fd = NULL;
- X }
- X/* do "F" commands */
- X
- Xdo_f()
- X {
- X struct buffcell *delete_p;
- X
- X switch (mapch_l[getcmdc(trace_sw)]) /* read next character and dispatch */
- X {
- X case '<': /* back to beginning of current iteration */
- X if (cptr.flag & F_ITER) /* if in iteration */
- X {
- X cptr.p = cptr.il->p; /* restore */
- X cptr.c = cptr.il->c;
- X cptr.dot = cptr.il->dot;
- X }
- X else for (cptr.dot = cptr.c = 0; cptr.p->b->b != NULL; cptr.p = cptr.p->b); /* else, restart current macro */
- X break;
- X
- X case '>': /* to end of current iteration */
- X find_enditer(); /* find it */
- X if ( ( ((esp->flag1) ? esp->val1 : srch_result) >= 0) ? (~colonflag) : colonflag) /* if exit */
- X pop_iteration(0); /* and exit if appropriate */
- X break;
- X
- X case '\'': /* to end of conditional */
- X case '|': /* to "else," or end */
- X find_endcond(cmdc);
- X break;
- X
- X/* "F" search commands */
- X
- X case 'b': /* bounded search, alternative args */
- X do_fb();
- X break;
- X
- X case 'c': /* bounded search, alternative args, then "FR" */
- X if (do_fb()) goto do_fr;
- X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
- X break;
- X
- X case 'n': /* do "N" and then "FR" */
- X if (do_nsearch('n')) goto do_fr;
- X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
- X break;
- X
- X case '_': /* do "_" and then "FR" */
- X if (do_nsearch('_')) goto do_fr;
- X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
- X break;
- X
- X case 's': /* search and replace: search, then do "FR" */
- X build_string(&sbuf); /* read search string and terminator */
- X if (end_search( do_search( setup_search() ) )) goto do_fr; /* if search passed, do "FR" */
- X while (getcmdc(trace_sw) != term_char); /* otherwise skip insert string */
- X break;
- X case 'r': /* replace last insert, search, etc. */
- X if (esp->flag1) ERROR(E_NFR); /* shouldn't have argument */
- X term_char = (atflag) ? getcmdc(trace_sw) : ESC; /* set terminator */
- X atflag = 0;
- X do_fr: /* entry from FN, F_, and FC */
- X set_pointer(dot, &cc); /* save a pointer to the current spot */
- X dot += ctrl_s; /* back dot up over the string */
- X set_pointer(dot, &aa); /* code from "insert1": convert dot to a qp */
- X delete_p = aa.p; /* save beginning of original cell */
- X if (dot < buff_mod) buff_mod = dot; /* update earliest char loc touched */
- X insert_p = bb.p = get_bcell(); /* get a new cell */
- X bb.c = 0;
- X ins_count = aa.c; /* save char position of dot in cell */
- X aa.c = 0;
- X
- X movenchars(&aa, &bb, ins_count); /* copy cell up to dot */
- X moveuntil(&cptr, &bb, term_char, &ins_count, cptr.z-cptr.dot, trace_sw); /* insert */
- X cptr.dot += ins_count; /* advance command-string pointer */
- X getcmdc(trace_sw); /* skip terminator */
- X
- X z += ctrl_s; /* subtract delete length from buffer count */
- X delete_p->b->f = insert_p; /* put the new cell where the old one was */
- X insert_p->b = delete_p->b; /* code borrowed from "insert2" */
- X insert_p = NULL;
- X
- X if (bb.c == cc.c) /* if replacement text was same length, we can save time */
- X {
- X for (; bb.c < CELLSIZE; bb.c++) bb.p->ch[bb.c] = cc.p->ch[bb.c]; /* copy rest of cell */
- X bb.p->f = cc.p->f; /* replace orig cell's place in chain with end of new list */
- X if (bb.p->f) bb.p->f->b = bb.p;
- X cc.p->f = NULL; /* terminate the part snipped out */
- X free_blist(delete_p); /* return the old part */
- X }
- X
- X else /* different positions: shift the remainder of the buffer */
- X {
- X bb.p->f = delete_p; /* splice rest of buffer to end */
- X delete_p->b = bb.p;
- X movenchars(&cc, &bb, z-dot); /* squeeze buffer */
- X free_blist(bb.p->f); /* return unused cells */
- X bb.p->f = NULL; /* and end the buffer */
- X }
- X
- X z += ins_count; /* add # of chars inserted */
- X dot += ins_count;
- X ctrl_s = -ins_count; /* save string length */
- X esp->flag1 = esp->flag2 = 0; /* and consume arguments */
- X esp->op = OP_START;
- X break;
- X
- X default:
- X ERROR(E_IFC);
- X }
- X }
- X/* routines for macro iteration */
- X/* pop iteration: if arg nonzero, exit unconditionally */
- X/* else check exit conditions and exit or reiterate */
- X
- Xpop_iteration(arg)
- X int arg;
- X {
- X if (!arg && (!cptr.il->dflag || (--(cptr.il->count) > 0)) ) /* if reiteration */
- X {
- X cptr.p = cptr.il->p; /* restore */
- X cptr.c = cptr.il->c;
- X cptr.dot = cptr.il->dot;
- X }
- X else
- X {
- X if (cptr.il->b) cptr.il = cptr.il->b; /* if not last thing on stack, back up */
- X else cptr.flag &= ~F_ITER; /* else clear "iteration" flag */
- X }
- X }
- X
- X
- X/* find end of iteration - read over arbitrary <> and one > */
- X
- Xfind_enditer()
- X {
- X register int icnt;
- X
- X for (icnt = 1; icnt > 0;) /* scan for matching > */
- X {
- X while ((skipto(0) != '<') && (skipc != '>')); /* scan for next < or > */
- X if (skipc == '<') ++icnt; /* and keep track of macro level */
- X else --icnt;
- X }
- X }
- X
- X
- X
- X/* find end of conditional */
- Xchar find_endcond(arg)
- X char arg;
- X {
- X register int icnt;
- X
- X for (icnt = 1; icnt > 0;)
- X {
- X while ((skipto(0) != '"') && (skipc != '\'') && (skipc != '|'));
- X if (skipc == '"') ++icnt;
- X else if (skipc == '\'') -- icnt;
- X else if ((icnt == 1) && (arg == '|')) break;
- X }
- X }
- X
- END_OF_te_exec2.c
- if test 29256 -ne `wc -c <te_exec2.c`; then
- echo shar: \"te_exec2.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- DONE=true
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- echo shar: You still need to run archive ${I}.
- DONE=false
- fi
- done
- if test "$DONE" = "true" ; then
- echo You have unpacked all 4 archives.
- echo "See the *.doc files"
- rm -f ark[1-9]isdone
- fi
- ## End of shell archive.
- exit 0
-